﻿using System;
using System.Text;
using System.Collections.Generic;
using System.Linq;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Pex.Framework;


namespace Benchmarks.McMinnThesisBen
{
    [TestClass, PexClass(typeof(VendingMachine))]    
    public class VendingMachine
    {
        static int CHOC_COST = 9;
        static int CRISPS_COST = 8;
        static int COKE_COST = 6;

        // change
        int ten_pennies = 10;
        int five_pennies = 10;
        int two_pennies = 10;
        int one_pennies = 10;

        // stock of various items
        int no_of_choc = 10;
        int no_of_crisps = 10;
        int no_of_coke = 10;
        // initialise
        int inserted = 0;

        public VendingMachine()
        {
            reset();
        }

        public void reset()
        {
            ten_pennies = 10;
            five_pennies = 10;
            two_pennies = 10;
            one_pennies = 10;
            no_of_choc = 10;
            no_of_crisps = 10;
            no_of_coke = 10;
            inserted = 0;
        }


        public bool check_have_change()
        {
            if (ten_pennies > 0 && five_pennies > 0 &&
            two_pennies > 0 && one_pennies > 0)
            {
                return true;
            }
            else
            {
                return false;
            }
        }

        public void insert_coinage(int coin, int amount)
        {
            if (coin == 1)
            {
                one_pennies += amount;
                inserted += amount;
            }
            else if (coin == 2)
            {
                two_pennies += amount;
                inserted += amount * 2;
            }
            else if (coin == 5)
            {
                five_pennies += amount;
                inserted += amount * 5;
            }
            else if (coin == 10)
            {
                ten_pennies += amount;
                inserted += amount * 10;
            }
        }

        public void buy_item(int item_id)
        {
            if (item_id == 0 && no_of_choc > 0)
            {
                if (inserted > CHOC_COST)
                {
                    inserted -= CHOC_COST;
                    no_of_choc -= 1;
                }
            }
            else if (item_id == 1 && no_of_crisps > 0)
            {
                if (inserted > CRISPS_COST)
                {
                    inserted -= CRISPS_COST;
                    no_of_crisps -= 1;
                }
            }
            else if (item_id == 2 && no_of_coke > 0)
            {
                if (inserted > COKE_COST)
                {
                    inserted -= COKE_COST;
                    no_of_coke -= 1;
                }
            }
       }

        public void change()
        {
            if (check_have_change())
            {
                while (inserted > 10 && ten_pennies > 0)
                {
                    inserted -= 10;
                    ten_pennies -=1;
                }
                while (inserted > 5 && five_pennies > 0)
                {
                    inserted -= 5;
                    five_pennies -=1;
                }
                while (inserted > 2 && two_pennies > 0)
                {
                    inserted -= 2;
                    two_pennies -= 1;
                }
                while (inserted > 1 && one_pennies > 0)
                {
                    inserted -= 1;
                    one_pennies -= 1;
                }
            }
        }

        //README of running these test methods with Pex
        //For each METHODNAME, run with C:\pex\bin\Debug>Pex Benchmarks.dll /mf:METHODNAME
        // adding /fte outputs all generated tests

        //seems fitness not working, need to debug more
        //[PexMethod(MaxRuns = 100, MaxConditions = int.MaxValue, MaxRunsWithoutNewTests = int.MaxValue)]        
        //public void TestVendingMachineFitness(int[] modifiers,
        //                                int[] arg1,
        //                                int[] arg2)
        //{
        //    TestVendingMachine(modifiers, arg1, arg2);
        //}

        //[PexMethod(MaxRuns = 100, MaxConditions = int.MaxValue, MaxRunsWithoutNewTests = int.MaxValue)]        
        //public void TestVendingMachineDefault(int[] modifiers,
        //                                int[] arg1,
        //                                int[] arg2)
        //{
        //    TestVendingMachine(modifiers, arg1, arg2);
        //}

        //private void TestVendingMachine(int[] modifiers, 
        //                                int[] arg1,
        //                                int[] arg2)
        //{
        //    PexAssume.IsTrue(modifiers != null);
        //    PexAssume.IsTrue(arg1 != null);
        //    PexAssume.IsTrue(arg2 != null);
        //    PexAssume.IsTrue(modifiers.Length == arg1.Length);
        //    PexAssume.IsTrue(modifiers.Length == arg2.Length);


        //    VendingMachine c = new VendingMachine();
        //    for (int i = 0; i <= (modifiers.Length - 1); i++)
        //    {
        //        switch (modifiers[i])
        //        {
        //            case 0:
        //                c.insert_coinage(arg1[i], arg2[i]);
        //                break;
        //            case 1:
        //                c.buy_item(arg1[i]);
        //                break;
        //            case 2:
        //                c.get_change();
        //                break;
        //            default:
        //                c.reset();
        //                break;
        //        }
        //    }
        //    c.check_have_change();
        //}
    }
}
